﻿using Microsoft.TeamFoundation.VersionControl.Client;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SearchForWorkitemsChanges
{
    /// <summary>
    /// Class used by <see cref="BranchLazyLoader"/> and <see cref="FolderLazyLoader"/> to Lazy load children folders (ViewModel folder item base class).
    /// </summary>
    /// <seealso cref="BranchLazyLoader"/>
    /// <seealso cref="FolderLazyLoader" />
    internal abstract class TfsItemLazyLoader
    {
        private bool areChildrenLoaded; // used to know if a load has been done (if no children...)
        private readonly ObservableCollection<TfsItemLazyLoader> currentChildren; // List of all children
        private readonly Item mySelf; // Tfs item displayed

        private readonly ITfsInfoProvider tfsInfoProvider; // Tfs provider used to load children


        /// <summary>
        /// Initializes a new instance of the <see cref="TfsItemLazyLoader" /> class.
        /// </summary>
        /// <param name="tfsInfoProvider">The TFS information provider.</param>
        /// <param name="source">The TFS Item source.</param>
        /// <param name="parent">The TFS Item parent.</param>
        public TfsItemLazyLoader(ITfsInfoProvider tfsInfoProvider, Item source, Item parent = null)
        {
            this.mySelf = source;
            this.currentChildren = new ObservableCollection<TfsItemLazyLoader>();
            this.areChildrenLoaded = false;
            this.tfsInfoProvider = tfsInfoProvider;

            if (parent == null)
                this.Name = source.ServerItem;
            else
                this.Name = source.ServerItem.Replace(parent.ServerItem, "");
        }

        /// <summary>
        /// Gets the TFS Item displayed
        /// </summary>
        public Item MySelf { get { return this.mySelf; } }

        /// <summary>
        /// Gets TFS Item name (not the full path).
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// Gets the TFS Item children (load on first call).
        /// </summary>
        public IEnumerable<TfsItemLazyLoader> Children
        {
            get
            {
                if (!this.areChildrenLoaded)
                    lock (currentChildren)
                        if (!this.areChildrenLoaded)
                            this.LoadChildren();
                return this.currentChildren;
            }
        }

        /// <summary>
        /// Do the loadChildren
        /// </summary>
        private void LoadChildren()
        {
            this.areChildrenLoaded = true;
            ThreadPool.QueueUserWorkItem(
                (p) =>
                {
                    App.Current.Dispatcher.Invoke(() => this.currentChildren.Clear());
                    var childItems = this.tfsInfoProvider.GetFolders(this.mySelf.ServerItem);

                    foreach (var childItem in childItems)
                        if (childItem.IsBranch)
                            App.Current.Dispatcher.Invoke(() => this.currentChildren.Add(new BranchLazyLoader(this.tfsInfoProvider, childItem, this.mySelf)));
                        else
                            App.Current.Dispatcher.Invoke(() => this.currentChildren.Add(new FolderLazyLoader(this.tfsInfoProvider, childItem, this.mySelf)));
                });
        }


    }
}
